package com.atguigu.gmall.mq.listener;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.mq.config.DeadLetterMqConfig;
import com.atguigu.gmall.mq.config.DelayMessageConfig;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Date;

/**
 * 死信和插件的消息应答
 */
@Component
@Slf4j
public class DeadLetterListener {
    //手动应答基于插件的自定义延迟消息
    @RabbitListener(queues = {DelayMessageConfig.queue_delay_1})
    public void receiverDelayMessage(String msg, Message message, Channel channel){
        System.out.println(msg + "接收: " + new Date());
        this.receiverMessage(String.valueOf(msg),message,channel);
    }

    //手动应答基于死信的延迟消息
    @RabbitListener(queues = {DeadLetterMqConfig.queue_dead_2})
    public void receiverDeadLetterMessage(String msg, Message message, Channel channel){
        System.out.println(msg + "接收: " + new Date());
        this.receiverMessage(String.valueOf(msg),message,channel);
    }

    public void receiverMessage(String msg, Message message, Channel channel) {
        //手动消息应答
        try {
            System.out.println("直接接收消息：" + msg);
            System.out.println("接收消息对象中的消息体：" + new String(message.getBody()));
            //int x = 10 /0;
            //basicAck : 手动应答
            //deliveryTag : 消息的标识符
            //multiple : 是否批量应答消息    预取值  prefetch: 4  表示每次获取4个消息  在信道中
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        } catch (Exception e) {
            //判断是否是已经发送的消息:是则重发一遍,不是则将队列中的消息删除掉
            if (message.getMessageProperties().isRedelivered()){
                //消息已经发送过了
                log.error("此消息不能再重发消费了:{}", JSONObject.toJSONString(message));
                //拒绝应答  将队列中的消息 删除掉 不要影响到后面的消息的处理
                //deliveryTag : 消息的标识符
                //requeue  : 要求将消息放回队列  消费者重新获取一次消息
                try {
                    channel.basicReject(message.getMessageProperties().getDeliveryTag(),false);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }else {
                //1.2 是刚来的消息   给一次 重新发送消息的机会
                //deliveryTag : 消息的标识符
                //multiple : 是否批量应答消息    预取值  prefetch: 4  表示每次获取4个消息  在信道中
                //requeue  : 要求将消息放回队列  消费者重新获取一次消息
                log.info("是刚来的消息   给一次 重新发送消息的机会");
                try {
                    channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
}
